﻿using System;
using System.IO;
using System.Runtime.CompilerServices;
using System.Security.Cryptography;
using System.Text;
using UnityEngine;
using XLua;

/// <summary>
/// 常用工具类
/// </summary>
public class CommonTools
{
    /// <summary>
    /// 将时间戳转换为日期格式
    /// </summary>
    /// <param name="timeStamp">时间戳 long类型</param>
    /// <returns>时间为日期格式</returns>
    public static System.DateTime ConvertLongToDateTime(long timeStamp)
    {
        System.DateTime dtStart = System.TimeZone.CurrentTimeZone.ToLocalTime(new System.DateTime(1970, 1, 1));
        long lTime = long.Parse(timeStamp + "0000000");
        System.TimeSpan toNow = new System.TimeSpan(lTime);
        return dtStart.Add(toNow);
    }
    /// <summary>
    /// 获取当前时间并格式化
    /// </summary>
    /// <param name="format">格式化规则</param>
    /// <returns></returns>
    public static string GetNowTimeAndFormat(string format = "yyyy/MM/dd HH:mm:ss")
    {
        DateTime dt = DateTime.Now.ToLocalTime();

        return dt.ToString(format);
    }
    /// <summary>
    /// 将日期转换为时间戳
    /// </summary>
    /// <param name="time">时间</param>
    /// <param name="return_seconds">返回单位为秒</param>
    /// <returns>时间戳 返回单位为 秒</returns>
    public static long ConvertDateTimeToLong(System.DateTime time, bool return_seconds = true)
    {
        System.DateTime startTime = System.TimeZone.CurrentTimeZone.ToLocalTime(new System.DateTime(1970, 1, 1));
        if (return_seconds)
        {
            return (long)(time - startTime).TotalSeconds;
        }
        else
        {
            return (long)(time - startTime).TotalMilliseconds;
        }
    }
    /// <summary>
    /// 获取当前时间戳
    /// </summary>
    /// <returns>时间戳 返回单位为 毫秒</returns>
    public static long GetNowTimestamp()
    {
        return ConvertDateTimeToLong(System.DateTime.Now, false);
    }

    /// <summary>
    /// 获取文件的MD5码
    /// </summary>
    /// <param name="file_path">文件全路径</param>
    /// <returns></returns>
    public static string GetMD5Code(string file_path)
    {
        StringBuilder _stringBuilder = new StringBuilder();
        try
        {
            // 找到指定文件
            var fs = new FileStream(file_path, FileMode.Open);
            MD5 md5 = new MD5CryptoServiceProvider();
            var retVal = md5.ComputeHash(fs);
            fs.Close();

            foreach (var t in retVal)
            {
                _stringBuilder.Append(t.ToString("X"));
            }

            //Debug.Log("MD5:" + _stringBuilder);

            return _stringBuilder.ToString();
        }
        catch (Exception ex)
        {
            throw new Exception("Get File MD5 Fail, error:" + ex.Message);
        }
    }


    /// <summary>
    /// 递归复制该目录下的所有文件到目标目录
    /// </summary>
    /// <param name="form_path">将要被复制的目录</param>
    /// <param name="head_path">相对于被复制文件的相对路径的前一截</param>
    /// <param name="dest_root_path">目标根目录</param>
    public static void CopyAssetsToDestionDirRecursion(string form_path, string head_path, string dest_root_path)
    {
        //Debug.Log(form_path);
        //得到该目录下所有的文件信息和文件夹
        var all_from_lua_array = new DirectoryInfo(form_path).GetFileSystemInfos();

        //对得到的文件或文件夹信息进行操作
        foreach (var file_sys_info in all_from_lua_array)
        {
            //转换为文件
            FileInfo file = file_sys_info as FileInfo;
            //是文件，拷贝到对应的目录
            if (file != null)
            {
                if (file.Extension != ".meta" && file.Extension != ".manifest")
                {
                    CopyFile(file, head_path, dest_root_path);
                }
            }
            //是文件夹，继续递归目录得到下级文件和文件夹
            else
            {
                CopyAssetsToDestionDirRecursion(file_sys_info.FullName, head_path, dest_root_path);
            }
        }

    }

    /// <summary>
    /// 复制单个文件到目标对应的目录，保存目录结构
    /// </summary>
    /// <param name="file">被复制的文件</param>
    /// <param name="head_path">相对于被复制文件的相对路径的前一截</param>
    /// <param name="dest_root_path">复制到目的的根目录</param>
    private static void CopyFile(FileInfo file, string head_path, string dest_root_path)
    {
        //调试：打印路径
        //Debug.Log(file.FullName);
        //Debug.Log(head_path);

        //得到相对路径
        string path_relative = file.FullName.Replace(head_path.Replace("/", "\\"), "");
        //调试：打印相对路径 
        //Debug.Log(path_relative);

        //检测目录是否存在
        string dir = CommonTools.GetParentPath(dest_root_path + path_relative);
        //Debug.Log(dir);
        //无目录则创建目录
        if (!Directory.Exists(dir))
        {
            Directory.CreateDirectory(dir);
            //Debug.Log("!!!创建目录：" + dir);
        }

        //复制到目的地的相对路径
        File.Copy(file.FullName, dest_root_path + path_relative, true);

        //Debug.Log("!!!复制文件：" + dest_root_path + path_relative);
    }

    /// <summary>
    /// 获取文件夹下文件总数量
    /// </summary>
    /// <param name="dirInfo"></param>
    /// <returns></returns>
    public static int GetFilesCount(DirectoryInfo dirInfo)
    {
        int totalFile = 0;
        totalFile += dirInfo.GetFiles().Length;
        foreach (DirectoryInfo subdir in dirInfo.GetDirectories())
        {
            totalFile += GetFilesCount(subdir);
        }
        return totalFile;
    }


    /// <summary>
    /// 获取上一级目录
    /// </summary>
    /// <param name="dirInfo"></param>
    /// <returns></returns>
    public static string GetParentPath(string childPath)
    {
        DirectoryInfo val = new DirectoryInfo(childPath).Parent;
        string path = val.ToString().Replace("\\", "/");
        //Debug.Log("父目录：" + path);
        return path;
    }

    /// <summary>
    /// 写入Byte[]数据到本地
    /// </summary>
    /// <param name="filePath"></param>
    /// <param name="writeData"></param>
    public static void WriteDataToLocal(string filePath, byte[] data)
    {
        //父目录
        string parentPath = GetParentPath(filePath);
        //保证将要读写的目录存在
        if (!Directory.Exists(parentPath)) Directory.CreateDirectory(parentPath);

        //将下载的文件写入到本地
        using (FileStream fs = new FileStream(filePath, FileMode.Create))
        {
            fs.Write(data, 0, data.Length);
        }
    }

}

